// Copyright (c) 2025 Huawei Technologies Co., Ltd.
// openUBMC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Description: 封装和解析VMM消息报文

#include "VMMMessage.hpp"

const int HEADER_LEN = 8;

VMMMessage::VMMMessage() = default;

VMMMessage::~VMMMessage() = default;

std::vector<uint8_t> VMMMessage::Pack(uint8_t opCode, const std::vector<uint8_t>& data,
    uint8_t status, uint8_t sack, uint8_t seq) {

    const size_t totalLength = HEADER_LEN + data.size();
    std::vector<uint8_t> packData(totalLength);

    int length = data.size();

    packData[0] = static_cast<uint8_t> (opCode);                            // 第1字节表示操作码
    packData[1] = static_cast<uint8_t> (status & 0xff);                     // 第2字节表示状态码
    packData[2] = static_cast<uint8_t> (sack & 0xff);                       // 第3字节表示失败原因
    packData[3] = static_cast<uint8_t> (seq & 0xff);                        // 第4字节表示序列号
    packData[4] = static_cast<uint8_t> ((length & 0xff000000) >> 24);       // 第5字节表示消息长度4字节的高8位
    packData[5] = static_cast<uint8_t> ((length & 0x00ff0000) >> 16);       // 第6字节表示消息长度4字节的次高8位
    packData[6] = static_cast<uint8_t> ((length & 0x0000ff00) >> 8);        // 第7字节表示消息长度4字节的次低8位
    packData[7] = static_cast<uint8_t> (length & 0x000000ff);               // 第8字节表示消息长度4字节的低8位

    if (!data.empty()) {
        std::copy(data.begin(), data.end(), packData.begin() + HEADER_LEN);
    }
    return packData;
}

std::vector<uint8_t> VMMMessage::SffDataPack(uint8_t dataType, uint8_t state, uint32_t dataLength, uint8_t seq) {
    const size_t totalLength = HEADER_LEN + dataLength;
    std::vector<uint8_t> packData(totalLength);

    packData[0] = static_cast<uint8_t> (TRANS_SFF);                                         // 第1字节表示操作码
    packData[1] = static_cast<uint8_t> (((state & 0x0f) << 4) | (dataType & 0x0f));         // 第2字节表示状态码
    packData[2] = 0;                                                                        // 第3字节表示失败原因
    packData[3] = seq;                                                                      // 第4字节表示序列号
    packData[4] = static_cast<uint8_t> ((dataLength & 0xff000000) >> 24);                   // 第5字节表示消息长度4字节的高8位
    packData[5] = static_cast<uint8_t> ((dataLength & 0x00ff0000) >> 16);                   // 第6字节表示消息长度4字节的次高8位
    packData[6] = static_cast<uint8_t> ((dataLength & 0x0000ff00) >> 8);                    // 第7字节表示消息长度4字节的次低8位
    packData[7] = static_cast<uint8_t> (dataLength & 0x000000ff);                           // 第8字节表示消息长度4字节的低8位

    return packData;
}

bool VMMMessage::Unpack(const std::string& data) {
    if (data.length() < HEADER_LEN) {
        std::cerr << "Invalid packet data length: " << data.length() << std::endl;
        return false;
    }

    // 第0字节表示操作码
    opcode_ = static_cast<uint8_t>(data[0]);
    // 第1字节表示状态码
    status_ = static_cast<uint8_t>(data[1]);
    // 第2字节表示失败原因
    sack_ = static_cast<uint8_t>(data[2]);
    // 第3字节表示序列号
    seq_ = static_cast<uint8_t>(data[3]);


    // 按照big-endian解析报文头
    // 第4-7字节表示数据长度
    length_ = (static_cast<uint8_t>(data[4]) << 24) |           // 数据长度4字节的高8位
             (static_cast<uint8_t>(data[5]) << 16) |            // 数据长度4字节的次高8位
             (static_cast<uint8_t>(data[6]) << 8) |             // 数据长度4字节的次低8位
             static_cast<uint8_t>(data[7]);                     // 数据长度4字节的低8位

    // 检查报文长度是否匹配
    if (length_ != data.length() - HEADER_LEN) {
        std::cerr << "Data length mismatch: expected " << length_ << ", got " << data.length() - HEADER_LEN << std::endl;
        return false;
    }

    // 设置报文体
    data_.assign(data.begin() + HEADER_LEN, data.end());
    return true;
}

uint8_t VMMMessage::GetOpCode() const {
    return opcode_;
}

uint8_t VMMMessage::GetStatus() const {
    return status_;
}

uint8_t VMMMessage::GetSack() const {
    return sack_;
}

uint8_t VMMMessage::GetSeq() const {
    return seq_;
}

uint32_t VMMMessage::GetLength() const {
    return length_;
}

std::vector<uint8_t> VMMMessage::GetData() const {
    return data_;
}